<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>Cardinals and Ordinals</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
		<meta name="viewport" content="width=device-width initial-scale=1">
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta http-equiv="Content-Language" content="en-gb">

<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
  var popup = document.getElementById(material_id);
  popup.classList.toggle("show");
}
</script>

<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
		
	</head>
	<body class="commentary-font">
		<nav role="navigation">
		<h1><a href="../index.html"><img src="../docs-assets/Inform.png" height=72> </a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=0> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=0> inweb</a></li>
<li><a href="https://github.com/ganelson/intest"><img src="../docs-assets/github.png" height=0> intest</a></li>
</ul>
		</nav>
		<main role="main">
		<!-- Weave of 'Cardinals and Ordinals' generated by inweb -->
<div class="breadcrumbs">
    <ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../services.html">Services</a></li><li><a href="index.html">linguistics</a></li><li><a href="index.html#1">Chapter 1: Setting Up</a></li><li><b>Cardinals and Ordinals</b></li></ul></div>
<p class="purpose">To parse integers seen from a grammatical point of view.</p>

<ul class="toc"><li><a href="1-cao.html#SP1">&#167;1. Cardinal and ordinal numbers</a></li></ul><hr class="tocbar">

<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Cardinal and ordinal numbers.</b>We read a few low numbers in text, but larger numbers only in digits. Textual
numbers run from 0 to 12 since that's what clocks need.
</p>

<p class="commentary">By a cardinal we mean a number such as <span class="extract"><span class="extract-syntax">five</span></span> or <span class="extract"><span class="extract-syntax">351</span></span>.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;cardinal-number-in-words&gt;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">zero</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">one</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">two</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">three</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">four</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">five</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">six</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">seven</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">eight</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">nine</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">ten</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">eleven</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">twelve</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>And by an ordinal we mean a number such as <span class="extract"><span class="extract-syntax">fifth</span></span> or <span class="extract"><span class="extract-syntax">351st</span></span>; note that
this is not a noun, and isn't allowed as a constant value in Inform.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;ordinal-number-in-words&gt;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">zeroth</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">first</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">second</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">third</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">fourth</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">fifth</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">sixth</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">seventh</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">eighth</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">ninth</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">tenth</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">eleventh</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">twelfth</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>Those two nonterminals here simply supply text: for efficiency reasons we
don't actually parse against them, although they would give the correct response
if we did. Instead they're scanned for words which are marked with the appropriate
numbers.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Cardinals::preform_optimiser</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Cardinals::preform_optimiser</span></span>:<br/>Linguistics Module - <a href="1-lm.html#SP4">&#167;4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">NTI::every_word_in_match_must_have_my_NTI_bit</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;cardinal-number&gt;</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">NTI::every_word_in_match_must_have_my_NTI_bit</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;ordinal-number&gt;</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">wn</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">lexer_wordcount</span><span class="plain-syntax">; </span><span class="identifier-syntax">wn</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Vocabulary::test_flags</span><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">, </span><span class="identifier-syntax">NUMBER_MC</span><span class="plain-syntax">))</span>
<span class="plain-syntax">            </span><a href="1-cao.html#SP3" class="function-link"><span class="function-syntax">Cardinals::mark_as_cardinal</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">));</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Vocabulary::test_flags</span><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">, </span><span class="identifier-syntax">ORDINAL_MC</span><span class="plain-syntax">))</span>
<span class="plain-syntax">            </span><a href="1-cao.html#SP3" class="function-link"><span class="function-syntax">Cardinals::mark_as_ordinal</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">));</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">}</span>

<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Cardinals::mark_as_cardinal</span><span class="plain-syntax">(</span><span class="identifier-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ve</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">NTI::mark_vocabulary</span><span class="plain-syntax">(</span><span class="identifier-syntax">ve</span><span class="plain-syntax">, </span><span class="function-syntax">&lt;cardinal-number&gt;</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>

<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Cardinals::mark_as_ordinal</span><span class="plain-syntax">(</span><span class="identifier-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ve</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">NTI::mark_vocabulary</span><span class="plain-syntax">(</span><span class="identifier-syntax">ve</span><span class="plain-syntax">, </span><span class="function-syntax">&lt;ordinal-number&gt;</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>

<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Cardinals::enable_in_word_form</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">Cardinals::enable_in_word_form</span></span>:<br/>Linguistics Module - <a href="1-lm.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">NTI::give_nt_reserved_incidence_bit</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;cardinal-number&gt;</span><span class="plain-syntax">, </span><span class="identifier-syntax">CARDINAL_RES_NT_BIT</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">NTI::give_nt_reserved_incidence_bit</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;ordinal-number&gt;</span><span class="plain-syntax">, </span><span class="identifier-syntax">ORDINAL_RES_NT_BIT</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">Nonterminals::make_numbering</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;cardinal-number-in-words&gt;</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">Nonterminals::flag_words_with</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;cardinal-number-in-words&gt;</span><span class="plain-syntax">, </span><span class="identifier-syntax">NUMBER_MC</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">Nonterminals::make_numbering</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;ordinal-number-in-words&gt;</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">Nonterminals::flag_words_with</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;ordinal-number-in-words&gt;</span><span class="plain-syntax">, </span><span class="identifier-syntax">ORDINAL_MC</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>Actual parsing is done here. We look at a single word to see if it's a
number literal: either one of the named cases above, or a number written out
in decimal digits, perhaps with a minus sign.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;cardinal-number&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Vocabulary::test_flags</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">), </span><span class="identifier-syntax">NUMBER_MC</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Vocabulary::get_literal_number_value</span><span class="plain-syntax">(</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)));</span>
<span class="plain-syntax">        </span><span class="named-paragraph-container code-font"><a href="1-cao.html#SP4_1" class="named-paragraph-link"><span class="named-paragraph">In Inform 7 only, check that the number is representable in the VM</span><span class="named-paragraph-number">4.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">        ==&gt; { </span><span class="identifier-syntax">N</span><span class="plain-syntax">, - };</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">}</span>

<span class="function-syntax">&lt;ordinal-number&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Vocabulary::test_flags</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">), </span><span class="identifier-syntax">ORDINAL_MC</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Vocabulary::get_literal_number_value</span><span class="plain-syntax">(</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)));</span>
<span class="plain-syntax">        </span><span class="named-paragraph-container code-font"><a href="1-cao.html#SP4_1" class="named-paragraph-link"><span class="named-paragraph">In Inform 7 only, check that the number is representable in the VM</span><span class="named-paragraph-number">4.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">        ==&gt; { </span><span class="identifier-syntax">N</span><span class="plain-syntax">, - };</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4_1" class="paragraph-anchor"></a><b>&#167;4.1. </b>These mustn't match any number too large to fit into the virtual machine
being compiled to, so "42000", for instance, is not a valid literal if Inform
is parsing text in a work intended for a 16-bit VM.
</p>

<p class="commentary">Why do we catch this here? The answer is probably that it's an excess of
caution, but this is a rare case where the choice of virtual machine affects
the legal syntax for Inform source text &mdash; text originally written for use on
Glulx, which allows for larger integers, might be moved over to a Z-machine
project, with the user not realising the consequences.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">In Inform 7 only, check that the number is representable in the VM</span><span class="named-paragraph-number">4.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Task::veto_number</span><span class="plain-syntax">(</span><span class="identifier-syntax">N</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="comment-syntax"> to prevent repetitions:</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Vocabulary::set_literal_number_value</span><span class="plain-syntax">(</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)), </span><span class="constant-syntax">1</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="1-cao.html#SP4">&#167;4</a> (twice).</li></ul>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. </b>A small variation which lifts this restriction on the number range:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;cardinal-number-unlimited&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Vocabulary::test_flags</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">), </span><span class="identifier-syntax">NUMBER_MC</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Vocabulary::get_literal_number_value</span><span class="plain-syntax">(</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)));</span>
<span class="plain-syntax">        ==&gt; { </span><span class="identifier-syntax">N</span><span class="plain-syntax">, - };</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
    <ul class="progressbar"><li class="progressprev"><a href="1-sc.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresscurrentchapter">1</li><li class="progresssection"><a href="1-lm.html">lm</a></li><li class="progresssection"><a href="1-dgr.html">dgr</a></li><li class="progresssection"><a href="1-sc.html">sc</a></li><li class="progresscurrent">cao</li><li class="progresschapter"><a href="2-adj.html">2</a></li><li class="progresschapter"><a href="3-vrb.html">3</a></li><li class="progresschapter"><a href="4-np.html">4</a></li><li class="progressnext"><a href="2-adj.html">&#10095;</a></li></ul></div>
</nav><!-- End of weave -->

		</main>
	</body>
</html>

